<template>
  <div class="dynamic_form_item">
    <a-form-item :name="props.question.key">
      <template v-slot:label>
        <label for="">{{ props.question.label }}</label>
        <a-tooltip v-if="props.question.state.tipText" :key="props.question.label" :title="props.question.state.tipText">
          <i class="iconfont" :style="{ marginLeft: '8px' }" :class="props.question.state.tipIconClassName"></i>
        </a-tooltip>
      </template>
      <div>
        <a-upload
          v-model:file-list="fileList"
          :accept="props.question.state.accept"
          :name="props.question.state.name || 'file'"
          :disabled="loadingFile || props.question.disabled || props.question.type == 'static' || props.config?.isView || false"
          :max-count="props.question.state.maxCount || (props.question.state.multiple ? 10 : 1)"
          :multiple="props.question.state.multiple || false"
          :list-type="props.question.state.listType || 'picture-card'"
          class="avatar-uploader"
          :action="url"
          :headers="headers"
          :data="props.question.state.params"
          :customRequest="customUpload"
          :before-upload="beforeUpload"
          @change="handleChange"
          @success="handleSuccess"
          @preview="handlePreview"
          @remove="handleRemove"
        >
          <div v-if="props.question.type == 'static'"></div>
          <div v-else-if="props.question.state.listType == 'text'">
            <a-button :loading="loadingFile">
              <!-- <upload-outlined /> -->
              <i class="iconfont icon-add"></i>
              上传文件
            </a-button>
            <p v-if="props.question.state.tip" style="margin-top: 10px">{{ props.question.state.tip }}</p>
          </div>
          <div v-else-if="fileList.length < (props.question.state.maxCount || (props.question.state.multiple ? 10 : 1))">
            <plus-outlined />
          </div>
        </a-upload>
        <p class="upload_p" v-if="props.question.state.tip && !props.question.state.listType" style="margin: 0">{{ props.question.state.tip }}</p>
      </div>
    </a-form-item>
    <a-modal :visible="previewVisible" :title="previewTitle" :footer="null" @cancel="handleCancel">
      <img alt="example" style="width: 100%" :src="previewImage" />
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { watch, getCurrentInstance, onMounted, ref } from 'vue';
import { QuestionBase } from '../../../question-base';
import { message, UploadProps } from 'ant-design-vue';
import { HOST } from '@/config';
import { PlusOutlined } from '@ant-design/icons-vue';
import { useUserStoreWithOut } from '@/store/modules/user';
import { downloadFile, fileUrl, uploadFile, uploadUrl } from '@/config/api/common/api';
import { Subscription } from 'rxjs';
import { filter } from 'rxjs/operators';
import { INFOSERVE, INITSERVE } from '@/mixins/subject/subject-types';
import { startPartUpload } from './sharding-upload';
import playBtn from './img/play-btn.png';
import { $Http } from '@/config/service/http';
let $subscribeSub: Subscription;

const fileList: any = ref([]);
//subject变量

const { proxy }: any = getCurrentInstance();
let props = defineProps<{ question: QuestionBase<any>; formData: any; config?: any }>();
const emit = defineEmits(['update:formData', 'parentServe']);
const fieldNames = props.question.state.fieldNames || null;
watch(
  () => props.question.value,
  (val) => {
    emit('update:formData', val);
    emit('parentServe', { key: 'isValidateFields', value: props.question.key });
    if (!isAutoSet.value) {
      init();
    } else {
      isAutoSet.value = false;
    }
  },
  { flush: 'sync' }
);

onMounted(() => {
  init();
  subWatch();
});

const fileFormat = (item)=>{
  if(!item) return ''
  let obj = {
    status: 'done',
    id: typeof item === 'object' ? (fieldNames ? item[fieldNames['fileId']] : item['id'] || item['fileId'] ): item,
    name: typeof item === 'object' ? (fieldNames ? item[fieldNames['name']] : item.name) : item,
    url: fileUrl(typeof item === 'object' ? (fieldNames ? item[fieldNames['fileId']] : item['id'] || item['fileId']) : item),
    size: fieldNames ? fieldNames['size'] : item?.size,
    suffix: fieldNames ? fieldNames['suffix'] : item?.suffix,
    thumbUrl: props.question.type === 'video' ? playBtn : null
  };
  return obj;
};

const init = () => {
  if (Array.isArray(props.question.value)) {
    fileList.value = props.question.value.map((item: any) => fileFormat(item));
  } else if (typeof props.question.value === 'object' && props.question.value !== null) {
    fileList.value = [props.question.value].map((item: any) => fileFormat(item));
  } else {
    if (props.question.value) {
      fileList.value = [
        {
          status: 'done',
          id: props.question.value,
          name: props.question.value,
          url: fileUrl(props.question.value),
          thumbUrl: props.question.type === 'video' ? playBtn : null
        }
      ];
      viewFile(props.question.value)
    }
  }
};

/* 上传文件
* @param params
*/
const viewFile = async (id:any = '') => {
 let obj = await $Http.api('dmsfile/resourceFileInfo/get', id, 'get');
 if(obj){
  console.log('文件对象',obj);
  return obj
 }
};

//监听动态表单数据完成
const subWatch = () => {
  $subscribeSub = proxy.$NotificationFormSub
    .getParams()
    .pipe(filter((res: any) => res !== 0))
    .subscribe((item: any) => {
      try {
        if (item.key === INFOSERVE) {
          //数据都全部都到了
          init();
        } else if (item.key === INITSERVE && item.value.initKeys.includes(props.question.key)) {
          init();
        }
      } catch (error) {}
    });
};

const userStore = useUserStoreWithOut();
let accessToken: any = userStore.getToken;

const url = ref(`${props.question.state.url ? HOST + props.question.state.url : uploadUrl}`);
const headers = {
  token: `${accessToken}`
};

const loadingFile = ref<boolean>(false);
const loading = ref<boolean>(false);
const previewVisible = ref(false);
const previewImage = ref('');
const previewTitle = ref('');

let shardSize = 5 * 1024 * 1024; //5M

//查看图片
const handlePreview = async (file: any) => {
  console.log('input-upload\input-upload.component.vue', 'handlePreview', file);
  if (props.question.state.previewFile) {
    return previewFile(file);
  }
  if (!props.question.state.isImage) {
    return updateFile(file);
  }
  if (!file.url && !file.preview) {
    file.preview = await getBase64(file.originFileObj, () => {});
  }
  previewImage.value = file.url || file.preview;
  previewVisible.value = true;
  previewTitle.value = file.name || file.url.substring(file.url.lastIndexOf('/') + 1);
};
// 下载文件
function updateFile(file) {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', `${HOST}${props.question.state.viewUrl}/${file.name}`, true);
  xhr.setRequestHeader('token', accessToken);
  xhr.responseType = 'blob';
  xhr.onload = function (e) {
    //如果请求执行成功
    if (this.status == 200) {
      var blob = this.response;
      const nameStr = xhr.getResponseHeader('content-disposition') || '';
      const filename = nameStr.split('=')[1] || file.name;
      var a = document.createElement('a'); // blob.type = "application/octet-stream"; //创键临时url对象
      var url = URL.createObjectURL(blob);
      a.href = url;
      a.download = filename;
      a.click(); //释放之前创建的URL对象
      window.URL.revokeObjectURL(url);
    }
  }; //发送请求
  xhr.send();
}

const isUpload = ref(false);
const customUpload = (info: any) => {
  const fileName = info.file?.name;
  if (fileName?.length > 50) {
    message.error('请上传名称长度在50内的文件！');
    fileList.value.splice(fileList.value.length - 1, 1);
    return;
  }
  isUpload.value = true;
  if (info.file.size > shardSize) {
    //大于5M分片上传
    startPartUpload(
      info,
      loadingFile,
      (data) => {
        if (!data) {
          isUpload.value = false; //上传完毕
          fileList.value.splice(fileList.value.length - 1, 1);
          return;
        }
        info.file.id = data.id;
        info.onSuccess(data, info.file);
        echoView();
        isUpload.value = false;//上传完毕
      },
      (info) => {
        console.log('报错了', info, fileList.value);
        deleteFile(info);
        isUpload.value = false;//上传完毕
      }
    );
  } else {
    //普通上传
    uploadFile({ file: info.file }, props.question.state.httpOpt || {})
      .then((res: any) => {
        if (res && res.data) {
          console.log('上传数据', res);
          info.onSuccess(res.data, info.file);
          echoView();
        } else {
          fileList.value.splice(fileList.value.length - 1, 1);
        }
        isUpload.value = false;//上传完毕
      })
      .catch((err) => {
        fileList.value.splice(fileList.value.length - 1, 1);
        isUpload.value = false;//上传完毕
      });
  }
  return;
};

//删除对应的文件
const deleteFile = (file) => {
  fileList.value.forEach((item, index) => {
    if (item.uid === file.file.uid) {
      fileList.value.splice(index, 1);
    }
  });
};

//上传回显图片
const echoView = () => {
  if (!fileList.value) return;
  console.log('准备赋值', fileList.value);
  fileList.value = fileList.value.map((info) => ({
    status: 'done',
    name: info.name,
    id: info.id,
    url: fileUrl(info.id),
    size: info.size,
    suffix: info.suffix,
    thumbUrl: info.thumbUrl ? info.thumbUrl : props.question.type === 'video' ? playBtn : null
  }));
  // if(!info) return
  // fileList.value = fileList.value.filter(data=>data.id);
  // if( props.question.state.multiple  ){
  //   fileList.value.push({
  //     status: 'done',
  //     name: info.name,
  //     id: info.id,
  //     url: fileUrl(info.id),
  //     size: info.size,
  //     suffix: info.suffix
  //   });
  // }else{
  //   fileList.value = [{
  //     status: 'done',
  //     name: info.name,
  //     id: info.id,
  //     url: fileUrl(info.id),
  //     size: info.size,
  //     suffix: info.suffix
  //   }];
  // }
  props.question.state.callback && props.question.state.callback(fileList.value);
  setValue();
};

//预览文件地址
function previewFile(file) {
  const params = Object.assign(props.question.state.params, { id: props.question.state.params?.previewId || file.id, expires: 2, timeUnit: 'HOURS' });
  proxy.$Http.api(props.question.state.viewUrl, params, 'post').then((data: any) => {
    if (data.success && data.data) {
      let a = document.createElement('a');
      a.href = data.data;
      a.target = '_blank';
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
    }
  });
}

//上传成功状态
const handleChange = (info: any) => {
  if (!isBeforeState.value) {
    fileList.value && fileList.value.length && fileList.value.splice(fileList.value.length - 1, 1);
    isBeforeState.value = true;
  }
  console.log('上传状态', info);
  if (info.file.status === 'done') {
    console.log('上传成功', info.file.response);
  }
  if (info.file.status === 'uploading') {
    loading.value = true;
    return;
  }
  if (info.file.status === 'error') {
    loading.value = false;
    message.error('upload error');
  }
};

//查看图片
const handleCancel = () => {
  previewVisible.value = false;
  previewTitle.value = '';
};

//赋值
const isAutoSet: any = ref(false);
const setValue = () => {
  isAutoSet.value = true;
  if (props.question.state.multiple) {
    //多个
    props.question.value = fileList.value
      .filter((res) => res)
      .map((res: any) => {
        let obj = {};
        if (fieldNames) {
          obj = {
            [fieldNames.fileId]: res.id,
            [fieldNames.name]: res.name,
            [fieldNames.size]: res.size,
            [fieldNames.suffix]: res.suffix
          };
        }
        return fieldNames ? obj : res.id;
      });
  } else {
    //单个
    if (fieldNames && fileList.value.length) {
      let obj = {
        [fieldNames.fileId]: fileList.value[0].id,
        [fieldNames.name]: fileList.value[0].name,
        [fieldNames.size]: fileList.value[0].size,
        [fieldNames.suffix]: fileList.value[0].suffix
      };
      props.question.value = obj;
    } else {
      props.question.value = fileList.value.length ? fileList.value[0].id : '';
    }
  }
  console.log('看下值fileList:', fileList.value);
  console.log('看下值value:', props.question.value);
};

//删除图片
const handleRemove = (file: any) => {
  const index = fileList.value.indexOf(file);
  const newFileList = fileList.value.slice();
  newFileList.splice(index, 1);
  fileList.value = newFileList;
  setValue();
  console.log('删除之后看下值', fileList.value, props.question.value);
};

//上传成功
const handleSuccess = (e: any) => {
  fileList.value[fileList.value.length - 1].status = 'done';
  fileList.value[fileList.value.length - 1].id = e.id;
  fileList.value[fileList.value.length - 1].name = e.name;
  fileList.value[fileList.value.length - 1].url = `${HOST}${props.question.state.viewUrl}/${e.id}`;
  setValue();
};

//上传限制
const isBeforeState: any = ref(true);
const beforeUpload = (file: any) => {
  return new Promise((resolve, reject) => {
    if (props.question.state.isImage) {
      const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
      if (!isJpgOrPng) {
        message.error('只能上传JPG、png格式的文件!');
        isBeforeState.value = false;
        return reject(false);
      }
    }
    const isLt2M = file.size / 1024 / 1024 < (props.question.state.size || 4096);
    if (!isLt2M && !props.question.state.cancelLimit) {
      message.error(`上传文件大小不能大于${props.question.state.size ? props.question.state.size + 'M' : '4G'}`);
      isBeforeState.value = false;
      return reject(false);
    }
    if (file.size === 0) {
      message.error(`上传文件为空文件`);
      isBeforeState.value = false;
      return reject(false);
    }
    isBeforeState.value = true;
    return resolve(true);
  });
};
//图片
function getBase64(img: Blob, callback: (base64Url: string) => void) {
  const reader = new FileReader();
  reader.addEventListener('load', () => callback(reader.result as string));
  reader.readAsDataURL(img);
}

//校验,是否正在上传
const submitVerify = () => {
  if( isUpload.value ){
    message.warning(`文件正在上传中……`);
  }
  return !isUpload.value; //是否上传完毕
};

//组件对外公开方法
defineExpose({
  submitVerify, //验证
});
</script>

<style lang="less" scoped>
@import url('./input-upload.component.less');
</style>
